#pragma once
#include <iostream>
#include "connection.hpp"
#include "log.hpp"
// 此文件处理到来的链接
class handler_connection
{
public:
    //构造函数：初始化函数对象
    handler_connection(func_t func)
        : _func(func)
    {
    }
    ~handler_connection()
    {
    }
    // 服务器从缓冲区读取信息，并调用回调函数，执行任务并响应
    void handler_recv(connection *con) 
    {
        LOG(DEBUG, "hanlder recv fd :%d \n", con->sockfd());
        while (true)
        {
            char buffer[1024];
            ssize_t n = ::recv(con->sockfd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                con->append_inbuffer(buffer);//将接受缓冲区读满
            }
            else
            {
                if (errno == EWOULDBLOCK || errno == EAGAIN)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    con->_excepter(con);//处理异常
                    return; // 一定要提前返回
                }
            }
        }
        _func(con);//本质是调用parse()函数：处理数据，做出响应
    }
    //发送数据
    void handler_send(connection *con)
    {
        //清空错误
        errno = 0;
        while(true)
        {
            ssize_t n = ::send(con->sockfd(),con->outbuffer().c_str(),con->outbuffer().size(),0);
            if(n > 0)
            {
                //n表示实际发送了多少数据
                con->out_buffer_remove(n);
                if(con->out_buffer_empty()) break;

            }
            else if(n == 0)//对方文件描述关闭
            {
                break;
            }
            else
            {
                if(errno == EWOULDBLOCK || errno == EAGAIN)//EWOULDBLOCK：在非阻塞IO操作中尝试读取没有数据可以读的文件描述符或写入一个没有空间可写的文件描述符
                {
                    break;
                }
                else if(errno == EINTR)//系统调用或函数调用被函数中断
                {
                    continue;
                }
                else
                {
                    con->_excepter(con);//异常处理
                    return;
                }
            }
        }
        //当输出缓冲区中还有数据时，开启写事件关心
        if(!con->out_buffer_empty())
        {
            con->_r->enable_read_write(con->sockfd(),true,true);
        }
        else
        {
            con->_r->enable_read_write(con->sockfd(),true,false);
        }
    }
    void handler_excpter(connection *con)
    {
        errno = 0;
        LOG(DEBUG,"client quit :%s\n",con->sockfd());
        con->_r->remove_connection(con->sockfd());
    }

private:
    func_t _func;//parse函数回调
};